import eventUtil from "./eventUtil";
import { settingUtil } from "./settingUtil";
import Common from "../../utils/Common";
import { CategoryConst, EventConst } from "../../const/Const";
import { GameStoreDetail } from "../../../sheets/vo/GameStoreDetail";
import { rackModel } from "../../model/rackModel";
import { shopModel } from "../../model/shopModel";
import { categoryModel } from "../../model/categoryModel";
import { autoTaskModel } from "../../model/autoTaskModel";
import { taskGoodsModel } from "../../model/taskGoodsModel";
import { missionModel } from "../../model/missionModel";
import { eventDefine, guideStep } from "../../../scripts/CustomDefine";
import { stepModel } from "../../model/stepModel";
import { dropMoneyModel } from "../../model/dropMoneyModel";
import { ModelComponent, Vec3 } from "cc";
import { freeTrialModel } from "../../model/freeTrialModel";
import { unlockModel } from "../../model/unlockModel";
import { stoneModel } from "../../model/stoneModel";
import { Debug } from "../../utils/Debug";
import { levelModel } from "../../model/LevelModel";
import { checkinModel } from "../../model/checkinModel";

export default class dataUtil {

    private static TOKEN: string = "CCC3_FRAMEWORK_TOKEN";
    private static COIN: string = "CCC3_FRAMEWORK_COIN";
    private static CCC3_FRAMEWORK_DOLLAR: string = "CCC3_FRAMEWORK_DOLLAR";
    private static GUIDE_STEP: string = "CCC3_FRAMEWORK_GUIDE_STEP";
    private static CURRENT_NEW_USER: string = "CCC3_FRAMEWORK_NEW_USER";
    private static CURRENT_MISSION: string = "CURRENT_MISSION";
    private static CCC3_DROP_MONEY: string = "CCC3_DROP_MONEY";
    private static CCC3_FRAMEWORK_CHECK_IN: string = "CCC3_FRAMEWORK_CHECK_IN";

    private static LOCAL_RACK_INFO: string = "LOCAL_RACK_INFO";
    private static LOCAL_SCALES: string = "LOCAL_SCALES";
    private static LOCAL_AUTO_TASK: string = "LOCAL_AUTO_TASK";
    private static LOCAL_AUTO_TASK_GOODS = "LOCAL_AUTO_TASK_GOODS";

    private static mUserToken: string = "";
    private static VIBRATE_SWITCH: string = "CCC3_FRAMEWORK_VIBRATE_SWITCH";


    /**
     * 游戏等级
     */
    private static GAME_LEVEL: string = "GAME_LEVEL";
    private static CURRENT_LEVEL: string = "CURRENT_LEVEL";
    /**
     * 商品详情
     */
    private static STORE_DETAIL: string = "STORE_DETAIL";
    /**
     * 商品品类解锁
     */
    private static UNLOCK_CATEGORY: string = "UNLOCK_CATEGORY";

    private static CCC3_FRAMEWORK_TAG: string = "CCC3_FRAMEWORK_TAG";
    public static setFrameworkTag(v: string) {
        settingUtil.setValue(this.CCC3_FRAMEWORK_TAG, v, true);
    }

    public static getFrameworkTag() {
        return settingUtil.getString(this.CCC3_FRAMEWORK_TAG, "");
    }

    private static mCoin: number = 0;

    public static getCoin() {
        return settingUtil.getInt(this.COIN, 0);
    }
    public static subCoin(v: number) {
        settingUtil.appendInt(this.COIN, -v);
        eventUtil.sendEventImmediately(EventConst.COIN_CHANGED, this.mCoin);
    }
    public static addCoin(v: number) {
        settingUtil.appendInt(this.COIN, v);
        eventUtil.sendEventImmediately(EventConst.COIN_CHANGED, this.mCoin);
    }
    public static setCoin(v: number) {
        settingUtil.setValue(this.COIN, "" + v, false);
        eventUtil.sendEventImmediately(EventConst.COIN_CHANGED, this.mCoin);
    }
    public static saveCoin() {
        let coin = this.getCoin();
        settingUtil.setValue(this.COIN, coin, true);
        // Lite.event.sendEventImmediately(EventConst.COIN_CHANGED, this.mCoin);
    }
    public static addDollar(v: number) {
        let dollar = settingUtil.appendInt(this.CCC3_FRAMEWORK_DOLLAR, v, true);
        eventUtil.sendEventImmediately(EventConst.DOLLAR_CHANGED, dollar);
    }
    public static getDollar() {
        let dollar = settingUtil.getInt(this.CCC3_FRAMEWORK_DOLLAR, 0);
        return dollar;
    }


    public static getToken() {
        if (Common.isEmpty(this.mUserToken))
            this.mUserToken = settingUtil.getString(this.TOKEN, "");
        return this.mUserToken
    }
    public static setToken(v: string) {
        settingUtil.setValue(this.TOKEN, v, true);
    }

    /**
     * 是否新手
     * @returns 
     */
    public static getIsNew() {
        return settingUtil.getBool(this.CURRENT_NEW_USER, true);
    }
    /**
     * 设置新手状态
     * @param on 
     */
    public static setIsNew(on: boolean) {
        settingUtil.setBool(this.CURRENT_NEW_USER, on, true);
    }



    /**
     *  振动开关 true 打开 false 关闭
    */
    public static get isVibrate() {
        return settingUtil.getBool(this.VIBRATE_SWITCH, true);;
    }
    /**
     * 振动开关 true 打开 false 关闭
     */
    public static set isVibrate(value) {
        settingUtil.setBool(this.VIBRATE_SWITCH, value, true);
        eventUtil.sendEventImmediately(EventConst.VIBRATESWITCH_CHANGED, value);
    }


    public static getStepObject(): Array<stepModel> {
        let stepAll = settingUtil.getObject(this.GUIDE_STEP, new Array<stepModel>());
        return stepAll;
    }

    /**
     * 当前引导的步骤
     * @returns 
     */
    public static getCurrentStep(): number {
        let stepAll = this.getStepObject();
        var currentStep = 0;
        stepAll = stepAll.sort((a, b) => {
            return b.step - a.step;
        })
        for (var i = 0; i < stepAll.length; i++) {
            if (stepAll == null) continue;
            if (stepAll[i].step >= currentStep) {
                if (stepAll[i].state)
                    currentStep = stepAll[i].step + 1;
                else
                    currentStep = stepAll[i].step;
                break;
            }
        }
        return currentStep;
    }
    /**
     * 检测引导的步骤
     * @returns 
     */
    public static testStep(step: guideStep) {
        let stepAll = this.getStepObject();
        for (var i = 0; i < stepAll.length; i++) {
            if (stepAll == null) continue;
            if (stepAll[i].step == step) {
                if (stepAll[i].state == 1)
                    return true;
            }
        }
        return false;
    }

    /**
     * 检测引导步骤的次数
     * @param step 
     * @param count 
     * @returns 
     */
    public static testStepCount(step: guideStep, count: number) {
        let stepAll = this.getStepObject();
        for (var i = 0; i < stepAll.length; i++) {
            if (stepAll == null) continue;
            if (stepAll[i].step == step) {
                if (stepAll[i].state == 1 && stepAll[i].count <= count)
                    return true;
            }
        }
        return false;
    }

    /**
     * 当前引导步骤结束
     * @param step 
     */
    public static stepEnd(step: guideStep) {
        let stepAll = this.getStepObject();
        let nowStep = stepAll.find(item => item.step == step);
        if (nowStep) {
            nowStep.state = 1;
            nowStep.count += 1;
        }
        else {
            nowStep = new stepModel(step, 1, 1);
            stepAll.push(nowStep);
            nowStep = new stepModel(step + 1, 0, 0);
            stepAll.push(nowStep);
        }
        settingUtil.setObject(this.GUIDE_STEP, stepAll, true);
        eventUtil.dispatchEvent(eventDefine.SHOW_DIALOG, { hide: true });
    }


    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * 关卡存储相关方方法
     */

    private static localLevelArray: Array<levelModel> = null!;
    /**
    * 当前通关的关卡 从0开始
    */
    public static getCurrentLevel(): number {
        this.getLevelObject();
        var currentLevel = 0;
        this.localLevelArray = this.localLevelArray.sort((a, b) => {
            return b.level - a.level;
        })
        for (var i = 0; i < this.localLevelArray.length; i++) {
            if (this.localLevelArray[i] == null) continue;
            if (this.localLevelArray[i].level >= currentLevel) {
                if (this.localLevelArray[i].state)
                    currentLevel = this.localLevelArray[i].level + 1;
                else
                    currentLevel = this.localLevelArray[i].level;
                break;
            }
        }
        return currentLevel;
    }


    /**
    * 增加关卡1
    */
    public static addCurrentLevel(num: number = 1) {
        var level = this.getCurrentLevel();
        this.updateLevel(level, true, 0, 1);
        level += num;
        this.updateLevel(level, false, 0, 1);
        eventUtil.dispatchEvent(EventConst.LEVEL_CHANGED, level);
    }

    public static setCurrentLevel(level: number, state: boolean) {
        this.getLevelObject();
        this.updateLevel(level, state, 0, 1);
        this.saveLevel();
    }


    public static createLevelItem(level: number, pass: boolean, time: number = 0, star: number = 1): levelModel {
        let obj: levelModel = new levelModel();
        obj.level = level;
        obj.state = pass;
        obj.time = time;
        obj.star = star;
        return obj;
    }




    /**
    * 更新缓存中的关卡数据
    */
    public static updateLevel(level: number, pass: boolean, time: number = 0, star: number = 1) {
        var item = this.getLevelItemByNo(level);
        if (item == null) {
            var newLevel = this.createLevelItem(level, pass, time, star);
            this.localLevelArray.push(newLevel);
            this.saveLevel();
        }
        else {
            if (pass) {
                item.state = pass;
                if (time <= item.time) {
                    item.time = time;
                }
                if (star > item.star) {
                    item.star = star;
                }
                this.saveLevel();
            }
        }
        // Debugger.LogInfo("更新关卡缓存 level:{0}  localLevelArray:{1} ", no, Utility.Json.Serialize(localLevelArray));
    }

    public static getLevelItemByNo(level: number): levelModel {
        this.getLevelObject();
        for (var i = 0; i < this.localLevelArray.length; i++) {
            if (this.localLevelArray[i] != null && this.localLevelArray[i].level == level) {
                var itemVal = this.localLevelArray[i];
                return itemVal;
            }
        }
        return null;
    }

    public static getLevelObject(): Array<levelModel> {
        if (this.localLevelArray == null) {
            var detailStr = settingUtil.getString(this.GAME_LEVEL, "");
            if (Common.isEmpty(detailStr))
                this.localLevelArray = new Array<levelModel>();
            else
                this.localLevelArray = JSON.parse(detailStr);
            Debug.log(`"GetLevelObject :{}" `, detailStr);
        }
        return this.localLevelArray;
    }

    public static saveLevel(): void {
        if (this.localLevelArray != null) {
            for (let i = 0; i < this.localLevelArray.length; i++) {
                if (this.localLevelArray[i] == null) {
                    this.localLevelArray.splice(i, 1);
                    i--;
                }
            }
            settingUtil.setObject(this.GAME_LEVEL, this.localLevelArray, true);
        }
    }

    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * 本地解锁商品品类相关方法
     */

    private static localCategory: Array<categoryModel> = null;
    public static getLocalUnlockCategoryAll(): Array<categoryModel> {
        if (this.localCategory == null) {
            var detailStr = settingUtil.getString(this.UNLOCK_CATEGORY, "");
            if (Common.isEmpty(detailStr)) {
                this.localCategory = new Array<categoryModel>();
            }
            else {
                this.localCategory = JSON.parse(detailStr);
            }
        }
        return this.localCategory;
    }

    public static addLocalUnlockCategory(category: categoryModel) {
        this.getLocalUnlockCategoryAll();
        if (this.localCategory != null) {
            var idx = this.getLocalUnlockCategoryIndexByCategoryId(category.categoryId);
            if (idx == -1) {
                this.localCategory.push(category);
            }
            else {
                this.localCategory[idx] == category;
            }

            this.saveUnlockCategory();
        }
    }

    public static getLocalUnlockCategoryIndexByCategoryId(categoryId: number): number {
        for (let i = 0; i < this.localCategory.length; i++) {
            if (this.localCategory[i].categoryId == categoryId) {
                return i;
            }
        }
        return -1;
    }

    public static isUnlockCategoryById(categoryId: number): boolean {
        this.getLocalUnlockCategoryAll();
        var idx = this.getLocalUnlockCategoryIndexByCategoryId(categoryId);
        if (idx != -1) {
            return this.localCategory[idx].isUnLocked;
        }
        return false;
    }

    public static saveUnlockCategory() {
        if (this.localCategory != null)
            settingUtil.setObject(this.UNLOCK_CATEGORY, this.localCategory, true);
    }



    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * 本地解锁商品相关方法
     */

    private static localStoreDetail: Array<shopModel> = null;
    /**
     * 本地存储的所有购买商品信息
     */
    public static getLocalAllShopDetail(): Array<shopModel> {
        if (this.localStoreDetail == null) {
            this.localStoreDetail = settingUtil.getObject(this.STORE_DETAIL, new Array<shopModel>());
        }
        return this.localStoreDetail;
    }
    /**
     * 根据ID获取本地存储的购买商品信息
     */
    public static getLocalShopDetailById(detailId: number): shopModel {
        this.getLocalAllShopDetail();
        for (var i = 0; i < this.localStoreDetail.length; i++) {
            if (this.localStoreDetail[i] != null && this.localStoreDetail[i].detailId == detailId) {
                var itemVal = this.localStoreDetail[i];
                return itemVal;
            }
        }
        return null;
    }

    /**
     * 根据ID获取本地存储的购买商品Index
     */
    public static getLocalShopDetailIndexById(detailId: number): number {
        this.getLocalAllShopDetail();
        for (var i = 0; i < this.localStoreDetail.length; i++) {
            if (this.localStoreDetail[i] != null && this.localStoreDetail[i].detailId == detailId) {
                return i;
            }
        }
        return -1;
    }

    /**
      * 根据类型ID获取本地存储的购买商品信息
      */
    public static getLocalShopDetailByCategoryId(...categoryArray: Array<number>): Array<shopModel> {
        this.getLocalAllShopDetail();
        return this.localStoreDetail.filter(item => categoryArray.indexOf(item.categoryId) != -1);
    }
    /**
     * 添加一个购买商品信息
     */
    public static createDetail(categoryId: number, detailId: number, num: number, active: boolean = false, isLocked: boolean = true): shopModel {
        var obj = new shopModel();
        obj.detailId = detailId;
        obj.categoryId = categoryId;
        obj.num = num;
        obj.active = active;
        obj.isLocked = isLocked;
        return obj;
    }
    /**
    * 获取购买的商品数量
    */
    public static getLocalDetailNumById(detailId: number): number {
        var item = this.getLocalShopDetailById(detailId);
        if (item == null) {
            return 0;
        }
        return item.num;
    }

    /**
     * 增加购买的商品数量
     * @param category 产品种类
     * @param detailId 产品ID
     * @param chipnum 需要解锁的数量
     * @param active 解锁是否激活
     * @param addNum 增加数量
     * @returns 
     */
    public static addLocalDetailNum(category: number, detailId: number, chipnum: number, active: boolean = true, addNum: number = 1, isSaveToLocal: boolean = true) {
        var item = this.getLocalShopDetailById(detailId);
        if (item == null) {
            item = this.createDetail(category, detailId, addNum, active, addNum < chipnum);
            this.localStoreDetail.push(item);
            if (isSaveToLocal)
                this.saveLocalStore();
            return;
        }
        let num = this.getLocalDetailNumById(detailId);
        item.num = num + addNum;
        if (item.num >= chipnum) {
            item.isLocked = false;
            if (active) {
                // this.setLocalDetailUnActiveByCategoryId(category);
                item.active = active;
            }
            else {
                item.active = active;
            }
        }
        var idx = this.getLocalShopDetailIndexById(detailId);
        if (idx >= 0)
            this.localStoreDetail[idx] = item;
        if (isSaveToLocal)
            this.saveLocalStore();
    }

    /**
     * 设置商品的数量
     * @param detailId 产品ID
     * @param num 增加数量
     * @returns 
     */
    public static setLocalDetailNum(detailId: number, num: number = 0) {
        var item = this.getLocalShopDetailById(detailId);
        if (item == null) return;
        item.num = num;
        var idx = this.getLocalShopDetailIndexById(detailId);
        if (idx >= 0)
            this.localStoreDetail[idx] = item;
        this.saveLocalStore();
    }

    /**
     * 重置产品的激活状态
     * @param categoryId 
     */
    public static setLocalDetailUnActiveByCategoryId(categoryId: number): void {
        for (var i = 0; i < this.localStoreDetail.length; i++) {
            var item = this.localStoreDetail[i];
            if (item.categoryId == categoryId) {
                this.localStoreDetail[i].active = false;
            }
        }
    }

    /**
     * 获取解锁并完成的子关卡数量
     * @param allSubMap 
     * @returns 
     */
    public static getUnlockSubNum(allSubMap: GameStoreDetail[]) {
        var unlockSubNum = 0;
        allSubMap.forEach((item) => {
            if (this.isUnlockByDetailId(item.DetailId) && this.isActiveByDetailId(item.DetailId)) {
                unlockSubNum++;
            }
        });
        return unlockSubNum;
    }


    public static clearLocalStore(): void {
        this.localStoreDetail = null;
        settingUtil.setObject(this.STORE_DETAIL, {}, true);
    }

    /**
     *  检查商品是否已经被解锁了 true 解锁  false 未解锁
     * @param detailId 产品ID
     * @returns 
     */
    public static isUnlockByDetailId(detailId: number): boolean {
        var detailInfo = GameStoreDetail.getStoreDetailByDetailId(detailId);
        if (detailInfo == null) return false;
        let num = this.getLocalDetailNumById(detailId);
        /**
         * 价格<=0 或 购买数量>=解锁数量 或 本地已经标记为解锁
         */
        var isUnlock = detailInfo.Amount <= 0 || num >= detailInfo.ChipNum
        if (!isUnlock) {
            let localDetail = this.getLocalShopDetailById(detailId);
            if (localDetail && !localDetail.isLocked) {
                isUnlock = true;
            }
        }
        return isUnlock;
    }

    /**
     *  检查商品是否已经激活了 true 激活  false 未激活
     * @param detailId 产品ID
     * @returns 
     */
    public static isActiveByDetailId(detailId: number): boolean {
        var detailInfo = GameStoreDetail.getStoreDetailByDetailId(detailId);
        if (detailInfo == null) return false;
        let localDetail = this.getLocalShopDetailById(detailId);
        return localDetail && localDetail.active;
    }

    public static saveLocalStore() {
        if (this.localStoreDetail != null) {
            settingUtil.setObject(this.STORE_DETAIL, this.localStoreDetail, true);
        }
    }

    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    *  货架相关
    */

    private static localRack: Array<rackModel>;
    /**
     * 所有货架信息
     * @returns 
     */
    public static getRacksAll(): Array<rackModel> {
        if (this.localRack == null) {
            this.localRack = settingUtil.getObject(this.LOCAL_RACK_INFO, new Array<rackModel>());
        }
        return this.localRack;
    }

    public static getRacksMaxLevel() {
        let stallsAll = this.getRacksAll();
        let maxLevel = 0;
        stallsAll.forEach(item => {
            if (maxLevel < item.level) {
                maxLevel = item.level;
            }
        });
        return maxLevel;
    }

    /**
    * 获取货架index
    * @returns 
    */
    public static getRackIndexById(rackId: number): number {
        var racks = this.getRacksAll();
        for (var i = 0; i < racks.length; i++) {
            var item = racks[i];
            if (item.rackId == rackId) {
                return i;
            }
        }
        return -1;
    }
    /**
     * 获取货架信息
     * @returns 
     */
    public static getRackById(rackId: number): rackModel {
        var racks = this.getRacksAll();
        for (var i = 0; i < racks.length; i++) {
            var item = racks[i];
            if (item.rackId == rackId) {
                return item;
            }
        }
        return null;
    }

    /**
     * 更新货架信息
     * @param rack 货架信息
     */
    public static updateRack(rack: rackModel) {
        this.getRacksAll();
        var idx = this.getRackIndexById(rack.rackId);
        if (idx == -1) {
            this.localRack.push(rack);
        }
        else {
            var temp = this.localRack[idx];
            temp.detailId = rack.detailId;
            temp.num = rack.num;
            this.localRack[idx] = rack;
        }
        eventUtil.dispatchEvent(eventDefine.STALLS_UPDATED, { detailId: rack.rackId });
    }
    /**
     * 获取货架的等级 
     * @param rackId 货架ID
     * @returns  没有解锁的返回0
     */
    public static getRackLevel(rackId: number) {
        var idx = this.getRackIndexById(rackId);
        if (idx > -1) {
            var temp = this.localRack[idx];
            return temp.level;
        }
        else {
            return 0
        }

    }
    /**
    * 升级货架
    */
    public static addRackLevel(rackId: number) {
        var idx = this.getRackIndexById(rackId);
        var temp = this.localRack[idx];
        temp.level++;
        this.localRack[idx] = temp;
        eventUtil.dispatchEvent(eventDefine.STALLS_UPDATED, { detailId: temp.rackId });
        this.saveRack();
    }

    /**
     * 清理货架信息
     */
    public static clearRackById(rackId: number) {
        this.getRacksAll();
        var idx = this.getRackIndexById(rackId);
        this.localRack.splice(idx, 1);
    }
    /**
    * 保存货架信息
    */
    public static saveRack() {
        if (this.localRack != null) {
            settingUtil.setObject(this.LOCAL_RACK_INFO, this.localRack, true);
        }
    }

    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    *  升级相关
    */

    private static mSales: number = -1;
    /**
     * 增加当前等级的销售量
     */
    public static addSales(num: number) {
        this.getSales();
        this.mSales += num;
        eventUtil.dispatchEvent(EventConst.SALES_CHANGED, this.mSales);
    }
    /**
     * 获取当前等级的销售量
     */
    public static getSales(): number {
        if (this.mSales == -1) {
            this.mSales = settingUtil.getInt(this.LOCAL_SCALES, 0);
        }
        return this.mSales;
    }
    /**
    * 清空当前等级的销售量
    */
    public static clearSales() {
        this.mSales = 0;
    }
    /**
    * 保存当前等级的销售量
    */
    public static saveSales() {
        settingUtil.setValue(this.LOCAL_SCALES, this.mSales, true);
    }


    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    *  自动赶山任务
    */

    private static mAutoTask: { [taskId: number]: autoTaskModel } = null;

    /**
     * 增加自动赶山任务
     * @param taskId    任务ID
     * @param mapId     地图ID
     */
    public static addAutoTask(taskId: number, mapId: number) {
        this.getAutoTask();
        this.mAutoTask[taskId] = new autoTaskModel(taskId, mapId);
        this.saveAutoTask();
    }
    /**
     * 获取自动赶山任务
     */
    public static getAutoTask(): { [taskId: number]: autoTaskModel } {
        if (this.mAutoTask == null) {
            this.mAutoTask = settingUtil.getObject(this.LOCAL_AUTO_TASK, new Array<autoTaskModel>());
        }
        return this.mAutoTask;
    }
    /**
     * 获取自动赶山任务
     */
    public static getAutoTaskById(taskId: number): autoTaskModel {
        this.getAutoTask();
        if (this.mAutoTask.hasOwnProperty(taskId)) {
            return this.mAutoTask[taskId];
        }
        return null;
    }
    public static getAutoMap() {
        let mapAll = GameStoreDetail.getStoreByCategoryIdAndParentId(CategoryConst.MAP, -1);
        let sortAll = mapAll.sort((a, b) => {
            return a.DetailId - b.DetailId;
        });

        let autoMap: Array<GameStoreDetail> = new Array<GameStoreDetail>();
        for (let i = 0; i < sortAll.length; i++) {
            let item = sortAll[i];
            if (dataUtil.isUnlockByDetailId(item.DetailId)) {
                let subAllMap = GameStoreDetail.getStoreByCategoryIdAndParentId(CategoryConst.MAP, item.DetailId);
                let noVideoSubMap = subAllMap.filter(item => item.VideoNum == 0);
                let unlockSubNum = dataUtil.getUnlockSubNum(noVideoSubMap);
                if (noVideoSubMap.length == unlockSubNum)
                    autoMap.push(item);
            }
        }
        // autoMap.splice(autoMap.length - 1, 1);
        return autoMap;
    }
    public static getAutoTaskByMapId(mapId: number): autoTaskModel {
        this.getAutoTask();
        for (let key in this.mAutoTask) {
            if (this.mAutoTask[key] && this.mAutoTask[key].mapId == mapId) {
                return this.mAutoTask[key];
            }
        }
        return null;
    }

    public static getAutoMapByMapId(mapId: number): GameStoreDetail {
        let mapAll = GameStoreDetail.getStoreByCategoryIdAndParentId(CategoryConst.MAP, -1);
        for (let i = 0; i < mapAll.length; i++) {
            let item = mapAll[i];
            if (item.DetailId == mapId) {
                return item;
            }
        }
        return null;
    }


    /**
    * 清空自动赶山任务
    */
    public static clearTask(taskId?: number) {
        if (this.mAutoTask != null && this.mAutoTask.hasOwnProperty(taskId)) {
            delete this.mAutoTask[taskId];
            this.saveAutoTask();
        }

    }

    public static saveAutoTask() {
        if (this.mAutoTask != null) {
            settingUtil.setObject(this.LOCAL_AUTO_TASK, this.mAutoTask, true);
        }
    }

    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    *  自动赶山产出的山货
    */

    private static mAutoTaskGoods: { [taskId: number]: taskGoodsModel } = null;
    public static getAutoTaskGoods() {
        if (this.mAutoTaskGoods == null)
            this.mAutoTaskGoods = settingUtil.getObject(this.LOCAL_AUTO_TASK_GOODS, {});
    }
    public static getAutoTaskGoodsById(taskId: number) {
        this.getAutoTaskGoods();
        if (this.mAutoTaskGoods.hasOwnProperty(taskId)) {
            return this.mAutoTaskGoods[taskId];
        }
        else {
            return null;
        }
    }
    public static addAutoTaskGoods(taskId: number, detailId: number, num: number, isSaveToLocal: boolean = true) {
        this.getAutoTaskGoods();
        let lastTime = Date.now();
        if (!this.mAutoTaskGoods.hasOwnProperty(taskId)) {
            this.mAutoTaskGoods[taskId] = { goods: [{ detailId, num, receiveNum: 0 }], lastTime };
        }
        else {
            let goods = this.mAutoTaskGoods[taskId].goods;
            let has: boolean = false;
            for (let i = 0; i < goods.length; i++) {
                if (goods[i].detailId == detailId) {
                    goods[i].num += num;
                    has = true;
                    break;
                }
            }
            if (!has) {
                goods.push({ detailId, num, receiveNum: 0 });
            }
            this.mAutoTaskGoods[taskId].goods = goods;
            this.mAutoTaskGoods[taskId].lastTime = lastTime;
        }
        if (isSaveToLocal)
            this.saveAutoTaskGoods();
    }

    public static getAutoTaskGoodsNumById(taskId: number) {
        this.getAutoTaskGoods();
        let total = 0;
        if (this.mAutoTaskGoods.hasOwnProperty(taskId)) {
            let goods = this.mAutoTaskGoods[taskId].goods;
            for (let i = 0; i < goods.length; i++) {
                total += goods[i].num;
            }
        }
        return total;
    }

    public static getAutoTaskAllNumById(taskId: number) {
        this.getAutoTaskGoods();
        let total = 0;
        if (this.mAutoTaskGoods.hasOwnProperty(taskId)) {
            let goods = this.mAutoTaskGoods[taskId].goods;
            for (let i = 0; i < goods.length; i++) {
                total += goods[i].num + goods[i].receiveNum;
            }
        }
        return total;
    }

    public static receiveAutoTaskGoods(taskId: number) {
        this.getAutoTaskGoods();
        if (this.mAutoTaskGoods.hasOwnProperty(taskId)) {
            let goods = this.mAutoTaskGoods[taskId].goods;
            for (let i = 0; i < goods.length; i++) {

                goods[i].receiveNum += goods[i].num;
                goods[i].num = 0;
            }
            this.saveAutoTaskGoods();
        }
    }


    public static clearAutoTaskGoods(taskId: number) {
        if (this.mAutoTaskGoods.hasOwnProperty(taskId)) {
            delete this.mAutoTaskGoods[taskId];
            this.saveAutoTaskGoods();
        }
    }

    public static saveAutoTaskGoods() {
        if (this.mAutoTaskGoods != null) {
            settingUtil.setObject(this.LOCAL_AUTO_TASK_GOODS, this.mAutoTaskGoods, true);
        }
    }


    /**
     * ************************************************************************************************************************
     * ************************************************************************************************************************
     * ************************************************************************************************************************
     * ************************************************************************************************************************
     *  系统任务
     */

    /**
     * 当前进行的任务 
     * 从1开始
     * @returns 
     */
    public static getCurrentMission(): missionModel {
        let mission = settingUtil.getObject(this.CURRENT_MISSION, new missionModel(1));
        return mission;
    }
    /**
     * 
     * @param mission 
     * @param isSaveToLocal 
     */
    public static setCurrentMission(mission: missionModel, isSaveToLocal: boolean = true, dispatch: boolean = true) {
        settingUtil.setObject(this.CURRENT_MISSION, mission, isSaveToLocal);
    }

    public static saveCurrentMission() {
        let mission: missionModel = this.getCurrentMission();
        settingUtil.setObject(this.CURRENT_MISSION, mission, true);
    }
    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    *  当前通关的地图
    */
    public static getCurrentMap() {
        let mapAll = GameStoreDetail.getStoreByCategoryIdAndParentId(CategoryConst.MAP, -1);
        let sortAll = mapAll.sort((a, b) => {
            return a.DetailId - b.DetailId;
        });
        let mainMap = sortAll[0];
        for (let i = 0; i < sortAll.length; i++) {
            let item = sortAll[i];
            if (!dataUtil.isUnlockByDetailId(item.DetailId)) {
                break;
            }
            else {
                mainMap = item;
            }
        }
        var allSubMap = GameStoreDetail.getStoreByCategoryIdAndParentId(CategoryConst.MAP, mainMap.DetailId);
        let currentMap = allSubMap[0];
        for (let i = 0; i < allSubMap.length; i++) {
            let item = allSubMap[i];

            if (!dataUtil.isUnlockByDetailId(item.DetailId)) {
                currentMap = item;
                break;
            }
            else {
                currentMap = item;
            }
        }
        return currentMap;
    }


    /**
     * ************************************************************************************************************************
     * ************************************************************************************************************************
     * ************************************************************************************************************************
     * ************************************************************************************************************************
     *  通用的免费试用
     */

    private static CCC3_FRAMEWORK_FREE_TRIAL: string = "CCC3_FRAMEWORK_FREE_TRIAL";

    public static getFreeTrial(key: string): freeTrialModel {
        let free: Array<freeTrialModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_FREE_TRIAL, new Array<freeTrialModel>());
        if (free.length > 0) {
            let current = free.find(item => item.key == key);
            if (current)
                return current;
            else
                return null;
        }
        return null;
    }

    public static isFreeTrial(key: string, freeNum: number = 1) {
        let free: Array<freeTrialModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_FREE_TRIAL, new Array<freeTrialModel>());
        if (free.length > 0) {
            let current = free.find(item => item.key == key);
            if (current) {
                let localDate = new Date(current.date);
                let localStr = Common.formatTime(localDate);
                let nowStr = Common.formatTime(new Date());
                if (localStr == nowStr) {
                    return current.num < freeNum;
                }
            }
        }
        return true;
    }

    public static addFreeTrial(key: string, detailId: number, freeNum: number = 1) {
        let free: Array<freeTrialModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_FREE_TRIAL, new Array<freeTrialModel>());
        let current = free.find(item => item.key == key);
        if (current) {
            let localDate = new Date(current.date);
            let localStr = Common.formatTime(localDate);
            let nowStr = Common.formatTime(new Date());
            current.detailId = detailId;
            if (localStr == nowStr) {
                current.num += freeNum;
            }
            else {
                current.num = freeNum;
                current.date = Date.now();
            }
        }
        else {
            let model = new freeTrialModel();
            model.key = key;
            model.num = freeNum;
            model.detailId = detailId;
            model.date = Date.now();
            free.push(model);
        }
        settingUtil.setObject(this.CCC3_FRAMEWORK_FREE_TRIAL, free, true);
    }

    /**
      * ************************************************************************************************************************
      * ************************************************************************************************************************
      * ************************************************************************************************************************
      * ************************************************************************************************************************
      *  通用的解锁判定
      */

    private static CCC3_FRAMEWORK_UNLOCK: string = "CCC3_FRAMEWORK_UNLOCK";

    public static getUnlockModel(detailId: number, category: CategoryConst): unlockModel {
        let isUnlock = false;
        let unlock: Array<unlockModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_UNLOCK, new Array<unlockModel>());
        let local = unlock.find(item => item.detailId == detailId && item.category == category);
        if (local) {
            return local;
        }
        return null;
    }

    /**
     * 判断是否解锁
     * @param detailId 
     * @param category 
     * @param unlockNum 
     * @returns 
     */
    public static isUnlockById(detailId: number, category: CategoryConst, unlockNum: number = 1, videoUnlockNum: number = 1): boolean {
        let isUnlock = false;
        let local = this.getUnlockModel(detailId, category);
        if (local) {
            isUnlock = (local.num >= unlockNum || local.locked == false || local.videoNum >= videoUnlockNum);
        }
        return isUnlock;
    }
    /**
     * 判断是否解锁
     * @param detailId 
     * @param category 
     * @param unlockNum 
     * @returns 
     */
    public static isVideoUnlockByDetailId(detailId: number, category: CategoryConst, videoUnlockNum: number = 1): boolean {
        let isUnlock = false;
        let local = this.getUnlockModel(detailId, category);
        if (local) {
            isUnlock = (local.locked == false || local.videoNum >= videoUnlockNum);
        }
        return isUnlock;
    }

    public static setUnlock(detailId: number, category: CategoryConst, num: number = 1, unlockNum: number = 1) {
        let unlock: Array<unlockModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_UNLOCK, new Array<unlockModel>());
        let local = unlock.find(item => item.detailId == detailId && item.category == category);
        if (local) {
            local.num = num;
            if (local.locked) {
                local.locked = !(local.num >= unlockNum)
            }
        }
        else {
            let model = new unlockModel();
            model.detailId = detailId;
            model.category = category;
            model.num = num;
            model.locked = !(num >= unlockNum);
            unlock.push(model);
        }
        settingUtil.setObject(this.CCC3_FRAMEWORK_UNLOCK, unlock, true);
    }


    /**
     * 更新解锁数据
     * @param detailId 
     * @param category 
     * @param num 
     * @param unlockNum 
     */
    public static addUnlock(detailId: number, category: CategoryConst, addNum: number = 1, unlockNum: number = 1) {
        let unlock: Array<unlockModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_UNLOCK, new Array<unlockModel>());
        let local = unlock.find(item => item.detailId == detailId && item.category == category);
        if (local) {
            local.num += addNum;
            if (local.locked) {
                local.locked = !(local.num >= unlockNum)
            }
        }
        else {
            let model = new unlockModel();
            model.detailId = detailId;
            model.category = category;
            model.num = addNum;
            model.locked = !(addNum >= unlockNum);
            unlock.push(model);
        }
        settingUtil.setObject(this.CCC3_FRAMEWORK_UNLOCK, unlock, true);
    }
    /**
    * 更新解锁数据
    * @param detailId 
    * @param category 
    * @param num 
    * @param unlockNum 
    */
    public static addVideoUnlock(detailId: number, category: CategoryConst, addNum: number = 1, unlockNum: number = 1) {
        let unlock: Array<unlockModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_UNLOCK, new Array<unlockModel>());
        let local = unlock.find(item => item.detailId == detailId && item.category == category);
        if (local) {
            local.videoNum += addNum;
            if (local.locked) {
                local.locked = local.videoNum >= unlockNum
            }
        }
        else {
            let model = new unlockModel();
            model.detailId = detailId;
            model.category = category;
            model.videoNum = addNum;
            model.locked = local.videoNum >= unlockNum;
            unlock.push(model);
        }
        settingUtil.setObject(this.CCC3_FRAMEWORK_UNLOCK, unlock, true);
    }



    /**
     * 获取购买的商品数量
     */
    public static getUnlockNumByDetailId(detailId: number, category: CategoryConst): number {
        let local = this.getUnlockModel(detailId, category);
        if (local == null) {
            return 0;
        }
        return local.num;
    }


    /**
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   *  签到
   */

    public static setCheckin(index: number, num: number, state: number, targetId?: number) {
        let checkArray: Array<checkinModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_CHECK_IN, new Array<checkinModel>());
        let model = checkArray.find(item => item.index == index);
        let nowTime = Date.now();
        if (model) {
            model.num = num;
            model.targetId = targetId;
            model.state = state;
        }
        else {
            model = new checkinModel(index, num, nowTime, state, targetId);
            checkArray.push(model);
        }

        settingUtil.setObject(this.CCC3_FRAMEWORK_CHECK_IN, checkArray, false);
    }

    public static saveCheckin(): void {
        let checkArray: Array<checkinModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_CHECK_IN, new Array<checkinModel>());
        settingUtil.setObject(this.CCC3_FRAMEWORK_CHECK_IN, checkArray, true);
    }

    public static isCheckin(index: number): boolean {
        let checkArray: Array<checkinModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_CHECK_IN, new Array<checkinModel>());
        let local = checkArray.find(item => item.index == index && item.state == 1);
        if (local) {
            return true;
        }
        return false;
    }

    public static hasCheckinData(index: number): boolean {
        let checkArray: Array<checkinModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_CHECK_IN, new Array<checkinModel>());
        let local = checkArray.find(item => item.index == index);
        if (local) {
            return true;
        }
        return false;
    }

    public static getCheckinDayIndex() {
        let checkArray: Array<checkinModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_CHECK_IN, new Array<checkinModel>());
        let firstCheckin = checkArray.find(item => item.index == 0);
        if (firstCheckin) {
            let idx = firstCheckin.index + Common.diffDate(Date.now(), firstCheckin.date);
            return idx;
        }
        return 0;
    }
    /**
     * 进入时是否能签到 false 不能签到  true 能签到
     * @returns 
     */
    public static isCheckinToday(): boolean {
        let checkArray: Array<checkinModel> = settingUtil.getObject(this.CCC3_FRAMEWORK_CHECK_IN, new Array<checkinModel>());
        //
        let firstCheckin = checkArray.find(item => item.index == 0);
        if (firstCheckin) {
            let t = Common.formatTime(new Date(firstCheckin.date));
            console.log('isCheckinToday', t)
            let diffDay = Common.diffDate(Date.now(), firstCheckin.date);
            //当天进入游戏
            if (diffDay == 0) {
                if (firstCheckin.state != 1)
                    return true;
                else
                    return false;
            }
            else {
                let otherCheckin = checkArray.find(item => item.index == diffDay);
                if (otherCheckin) {
                    if (otherCheckin.state != 1)
                        return true;
                    else
                        return false;
                }
                else {
                    return false;
                }
            }
        }
    }





    /**
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   *  掉落得钱币
   */

    public static getDropMoney(): Array<dropMoneyModel> {
        let dropMoneyArray = settingUtil.getObject(this.CCC3_DROP_MONEY, new Array<dropMoneyModel>());
        return dropMoneyArray;
    }


    public static setDropMoney(dropMoneyArray: Array<dropMoneyModel>) {

        settingUtil.setObject(this.CCC3_DROP_MONEY, dropMoneyArray, true);
    }

    public static saveDropMoney() {
        let dropMoneyArray: Array<dropMoneyModel> = this.getDropMoney();
        settingUtil.setObject(this.CCC3_DROP_MONEY, dropMoneyArray, true);
    }

    /**
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   * ************************************************************************************************************************
   *  掉落得钱币
   */
    public static CCC3_FRAMEWORK_OUTLINE_TIME: string = "CCC3_FRAMEWORK_OUTLINE_TIME";
    public static getOutlineTime(): number {
        return settingUtil.getInt(this.CCC3_FRAMEWORK_OUTLINE_TIME, Date.now());
    }

    public static setOutlineTime(time: number) {
        settingUtil.setValue(this.CCC3_FRAMEWORK_OUTLINE_TIME, time, true);
    }

    /**
     * 珍品的概率
     */
    public static TREASURE_PROP: string = "TREASURE_PROP";
    public static getTreasureProp(): number {
        return settingUtil.getFloat(this.TREASURE_PROP, 0);
    }
    public static addTreasureProp(num: number = 0.1) {
        let prop = this.getTreasureProp();
        prop += num;
        settingUtil.setValue(this.TREASURE_PROP, prop, true);
    }
    public static resetTreasureProp() {
        settingUtil.setValue(this.TREASURE_PROP, 0, true);
    }


    /**
    * 进入山洞时间
    */
    public static ENTER_CAVERN_TIME: string = "ENTER_CAVERN_TIME";
    public static getEnterCavernTime(): number {
        return settingUtil.getFloat(this.ENTER_CAVERN_TIME, 0);
    }
    public static addEnterCavernTime(num: number = 0.1) {
        let prop = this.getEnterCavernTime();
        prop += num;
        settingUtil.setValue(this.ENTER_CAVERN_TIME, prop, true);
    }
    public static setEnterCavernTime(v: number) {
        settingUtil.setValue(this.ENTER_CAVERN_TIME, v, true);
    }


    /**
     * 存储石头状态
     */
    public static STONE_STATE: string = "STONE_STATE";
    public static getStoneState(): stoneModel {
        return settingUtil.getObject(this.STONE_STATE, new stoneModel());
    }
    public static setStoneState(v: stoneModel) {
        settingUtil.setObject(this.STONE_STATE, v, true);
    }
    /**
     * 存储锤子数量
     */
    public static HAMMER_NUM: string = "HAMMER_NUM";
    public static getHummerNum(): number {
        return settingUtil.getInt(this.HAMMER_NUM, 0);
    }
    public static setHummerNum(v: number) {
        settingUtil.setValue(this.HAMMER_NUM, v, true);
    }

    /**
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    * ************************************************************************************************************************
    *  掉落得钱币
    */

    private static CCC3_PUSA_MONEY: string = "CCC3_PUSA_MONEY";
    public static getPusaMoney(): Array<dropMoneyModel> {
        let dropMoneyArray = settingUtil.getObject(this.CCC3_PUSA_MONEY, new Array<dropMoneyModel>());
        return dropMoneyArray;
    }

    public static setPusaMoney(dropMoneyArray: Array<dropMoneyModel>) {
        settingUtil.setObject(this.CCC3_PUSA_MONEY, dropMoneyArray, true);
    }

    public static savePusaMoney() {
        let dropMoneyArray: Array<dropMoneyModel> = this.getDropMoney();
        settingUtil.setObject(this.CCC3_PUSA_MONEY, dropMoneyArray, true);
    }

    /**
     * 菩萨上次一次的掉落钱币的时间
     */
    public static CCC3_PUSA_MONEY_TIME: string = "CCC3_PUSA_MONEY_TIME";
    public static getPusaMoneyTime(): number {
        return settingUtil.getInt(this.CCC3_PUSA_MONEY_TIME, Date.now());
    }
    public static setPusaMoneyTime(v: number) {
        settingUtil.setValue(this.CCC3_PUSA_MONEY_TIME, v, true);
    }


}